package com.tanhua.sso.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.sso.mapper.UserMapper;
import com.tanhua.sso.pojo.User;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private HuanXinService huanXinService;

    @Value("${jwt.secret}")
    private String secret;

    public String login(String mobile, String code) {
        Boolean isNew = false;

        String value = this.redisTemplate.opsForValue().get("CHECK_CODE_" + mobile);

        // 验证 验证码
        if (!StringUtils.equals(value, code)) {
            return null;
        }

        // 查询用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", mobile);
        User user = userMapper.selectOne(queryWrapper);
        // 没查到就往数据库插入一个新用户
        if (user == null) {
            User newUser = new User();
            newUser.setMobile(mobile);
            newUser.setPassword(DigestUtils.md5Hex(secret + "123456"));
            userMapper.insert(newUser);
            user = newUser;
            isNew = true;

            // 注册环信用户
            huanXinService.register(user.getId());
        }

        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put("mobile", mobile);
        claims.put("id", user.getId());

        // 生成token
        String tokenKey = Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, secret).compact();

        String token = "TOKEN_" + tokenKey;
        try {
            redisTemplate.opsForValue().set(token, MAPPER.writeValueAsString(user), Duration.ofHours(720));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        try {
            // RocketMQ发送登录成功的消息
            Map<String, Object> msg = new HashMap<>();
            msg.put("userId", user.getId());
            msg.put("date", new Date());
            this.rocketMQTemplate.convertAndSend("tanhua-sso-login", msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isNew + "|" + tokenKey;
    }

    public User queryUserByToken(String token) {
        try {
            String redisTokenKey = "TOKEN_" + token;
            String cacheData = this.redisTemplate.opsForValue().get(redisTokenKey);
            if (StringUtils.isEmpty(cacheData)) {
                return null;
            }
            // 刷新时间
            this.redisTemplate.expire(redisTokenKey, 1, TimeUnit.HOURS);
            return MAPPER.readValue(cacheData, User.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean savaPhone(User user) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", user.getId()).eq("mobile", user.getMobile());
        User selectOne = userMapper.selectOne(queryWrapper);
        if (selectOne == null) {
            userMapper.updateById(user);
            return true;
        }
        return false;
    }
}
